import 'dart:async';
import 'dart:io';

import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'package:common_utils/common_utils.dart';
import 'package:dio/dio.dart' as dio;
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';

import '../../../common/user_helper.dart';
import '../../../net/dio_utils.dart';
import '../../../utils/toast_utils.dart';

///代码清单12-8 首页面使用控制器
///lib/controller/home_controller.dart
class LocationGetController extends GetxController {
  ///定位权限
  bool noLocationPermisson = false;
  bool isAdCode = false;

  LocationGetController({this.isAdCode = false});

  ///当前位置
  String _currentAddress = "";
  String _adCode = "";

  ///今天天气
  String _currentWeatherInfo = "";

  String getCurrentWeather() {
    if (locationSuccess) {
      return _currentWeatherInfo ?? "";
    }
    return _currentWeatherInfo;
  }

  String getCurrentAddress() {
    if (locationSuccess) {
      return _currentAddress ?? "";
    }
    return locationFaileMessage;
  }

  /// 定位成功
  bool locationSuccess = false;
  String locationFaileMessage = "";

  Map<String, Object> _locationResult;

  StreamSubscription<Map<String, Object>> _locationListener;

  AMapFlutterLocation _locationPlugin = new AMapFlutterLocation();

  Future<bool> initFunction() async {
    /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看，如果未包含或者没有弹窗展示，高德定位SDK将不会工作
    ///
    /// 高德SDK合规使用方案请参考官网地址：https://lbs.amap.com/news/sdkhgsy
    /// <b>必须保证在调用定位功能之前调用， 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
    ///
    /// 高德SDK合规使用方案请参考官网地址：https://lbs.amap.com/news/sdkhgsy
    ///
    /// [hasContains] 隐私声明中是否包含高德隐私政策说明
    ///
    /// [hasShow] 隐私权政策是否弹窗展示告知用户
    AMapFlutterLocation.updatePrivacyShow(true, true);

    /// 设置是否已经取得用户同意，如果未取得用户同意，高德定位SDK将不会工作
    ///
    /// 高德SDK合规使用方案请参考官网地址：https://lbs.amap.com/news/sdkhgsy
    ///
    /// <b>必须保证在调用定位功能之前调用, 建议首次启动App时弹出《隐私政策》并取得用户同意</b>
    ///
    /// [hasAgree] 隐私权政策是否已经取得用户同意
    AMapFlutterLocation.updatePrivacyAgree(true);

    if (Platform.isAndroid) {
      /// 动态申请定位权限
      bool result = await requestPermission();
      if (!result) {
        noLocationPermisson = false;
        update(["locationRoot"]);
        return false;
      }
    }
    noLocationPermisson = true;

    ///设置Android和iOS的apiKey<br>
    ///
    /// 定位Flutter插件提供了单独的设置ApiKey的接口，
    /// 使用接口的优先级高于通过Native配置ApiKey的优先级（通过Api接口配置后，通过Native配置文件设置的key将不生效），
    /// 使用时可根据实际情况决定使用哪种方式
    ///
    ///key的申请请参考高德开放平台官网说明<br>
    ///
    ///Android: https://lbs.amap.com/api/android-location-sdk/guide/create-project/get-key
    ///
    ///iOS: https://lbs.amap.com/api/ios-location-sdk/guide/create-project/get-key

    AMapFlutterLocation.setApiKey(getAdCode(), getAdCode());

    ///iOS 获取native精度类型
    if (Platform.isIOS) {
      requestAccuracyAuthorization();
    }

    ///注册定位结果监听
    _locationListener = _locationPlugin
        .onLocationChanged()
        .listen((Map<String, Object> result) {
      Object errorObj = result["errorCode"];
      errorObj ??= "0";
      int errorCode = int.parse(errorObj.toString());
      LogUtil.e("获取定位结果 $errorCode");
      locationSuccess = false;
      if (errorCode == 0 && result["latitude"] != null) {
        UserHelper.getInstance.userLatitude =
            num.parse(result["latitude"].toString());
        UserHelper.getInstance.userLongitude =
            num.parse(result["longitude"].toString());
        _currentAddress = result["address"].toString();
        _adCode = result["adCode"].toString();
        UserHelper.getInstance.adCode = _adCode;
        UserHelper.getInstance.userAddress = _currentAddress;
        // if (Get.isRegistered<HomeItemController>()) {
        //   Get.find<HomeItemController>().onLocationSuccessRequest();
        // }
        locationSuccess = true;
        if (isAdCode && _currentWeatherInfo.isEmpty) {
          requestWeather();
        }
      } else if (errorCode == 1) {
        locationFaileMessage = "请对定位传递的参数进行非空判断。";
      } else if (errorCode == 2) {
        locationFaileMessage = "定位失败，由于仅扫描到单个wifi，且没有基站信息";
      } else if (errorCode == 3) {
        locationFaileMessage = "请对所连接网络进行全面检查，请求可能被篡改。";
      } else if (errorCode == 5) {
        locationFaileMessage = "请求被恶意劫持，定位结果解析失败。";
      } else if (errorCode == 7) {
        locationFaileMessage = "KEY鉴权失败。";
      } else if (errorCode == 9) {
        locationFaileMessage = "定位初始化时出现异常 请尝试关闭APP 重新进入。";
      } else if (errorCode == 11) {
        locationFaileMessage = "请检查是否安装SIM卡，设备很有可能连入了伪基站网络。";
      } else if (errorCode == 12) {
        locationFaileMessage = "请在设备的设置中开启app的定位权限。";
      } else if (errorCode == 13) {
        locationFaileMessage = "定位失败，由于未获得WIFI列表和基站信息，且GPS当前不可用。";
      } else if (errorCode == 14) {
        locationFaileMessage = "GPS 定位失败，由于设备当前 GPS 状态差。";
      } else if (errorCode == 15) {
        locationFaileMessage = "定位结果被模拟导致定位失败。";
      } else if (errorCode == 18) {
        locationFaileMessage = "G定位失败，由于手机WIFI功能被关闭同时设置为飞行模式。";
      } else if (errorCode == 19) {
        locationFaileMessage = "定位失败，由于手机没插sim卡且WIFI功能被关闭。";
      } else if (errorCode == -1) {
        locationFaileMessage = "获取位置失败 请尝试重新进入APP";
      }
      result.forEach((key, value) {
        LogUtil.e("定位 $key  $value");
      });
      update(["locationRoot"]);
    });

    Future.delayed(Duration.zero, () {
      startLocation();
    });
    update(["locationRoot"]);
    return true;
  }

  ///设置定位参数
  void _setLocationOption() {
    if (null != _locationPlugin) {
      AMapLocationOption locationOption = new AMapLocationOption();

      ///是否单次定位
      locationOption.onceLocation = false;

      ///是否需要返回逆地理信息
      locationOption.needAddress = true;

      ///逆地理信息的语言类型
      locationOption.geoLanguage = GeoLanguage.DEFAULT;

      locationOption.desiredLocationAccuracyAuthorizationMode =
          AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;

      locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

      ///设置Android端连续定位的定位间隔
      locationOption.locationInterval = 200000;

      ///设置Android端的定位模式<br>
      ///可选值：<br>
      ///<li>[AMapLocationMode.Battery_Saving]</li>
      ///<li>[AMapLocationMode.Device_Sensors]</li>
      ///<li>[AMapLocationMode.Hight_Accuracy]</li>
      locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

      ///设置iOS端的定位最小更新距离<br>
      locationOption.distanceFilter = -1;

      ///设置iOS端期望的定位精度
      /// 可选值：<br>
      /// <li>[DesiredAccuracy.Best] 最高精度</li>
      /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
      /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
      /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
      /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
      locationOption.desiredAccuracy = DesiredAccuracy.Best;

      ///设置iOS端是否允许系统暂停定位
      locationOption.pausesLocationUpdatesAutomatically = false;

      ///将定位参数设置给定位插件
      _locationPlugin.setLocationOption(locationOption);
    }
  }

  ///开始定位
  void startLocation() {
    _setLocationOption();
    _locationPlugin.startLocation();
  }

  ///获取iOS native的accuracyAuthorization类型
  void requestAccuracyAuthorization() async {
    AMapAccuracyAuthorization currentAccuracyAuthorization =
        await _locationPlugin.getSystemAccuracyAuthorization();
    if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
      print("精确定位类型");
    } else if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
      print("模糊定位类型");
    } else {
      print("未知定位类型");
    }
  }

  /// 动态申请定位权限
  Future<bool> requestPermission() async {
    // 申请权限
    bool hasLocationPermission = await requestLocationPermission();
    if (hasLocationPermission) {
      print("定位权限申请通过");
      return true;
    } else {
      print("定位权限申请不通过");
      return false;
    }
  }

  /// 申请定位权限
  /// 授予定位权限返回true， 否则返回false
  Future<bool> requestLocationPermission() async {
    //获取当前的权限
    var status = await Permission.location.status;
    if (status == PermissionStatus.granted) {
      //已经授权
      return true;
    } else {
      if (Platform.isAndroid) {
        dynamic press = await Get.defaultDialog(
            title: "温馨提示",
            middleText: "需要获取您的位置信息来 来计算签到的距离",
            backgroundColor: Colors.white,
            titleStyle: const TextStyle(color: Colors.black),
            middleTextStyle: const TextStyle(color: Colors.red),
            textConfirm: "同意",
            textCancel: "不同意",
            confirmTextColor: Colors.white,
            onConfirm: () {
              Get.back(result: true);
            },
            onCancel: () {
              Get.back(result: false);
            },
            radius: 8);
        if (press == null || !press) {
          noLocationPermisson = false;
          update(["locationRoot"]);
          return false;
        }
      }

      //未授权则发起一次申请
      status = await Permission.location.request();
      if (status == PermissionStatus.granted) {
        return true;
      } else {
        return false;
      }
    }
  }

  ///停止定位
  void _stopLocation() {
    if (null != _locationPlugin) {
      _locationPlugin.stopLocation();
    }
  }

  @override
  void onClose() {
    // TODO: implement onClose
    super.onClose();
    _stopLocation();

    ///移除定位监听
    if (null != _locationListener) {
      _locationListener.cancel();
    }

    ///销毁定位
    if (null != _locationPlugin) {
      _locationPlugin.destroy();
    }
  }

  void showLocationFunction(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        String title = "当前位置";
        String currentLocation = _currentAddress;
        if (!locationSuccess) {
          title = "定位失败";
          currentLocation = locationFaileMessage;
        }

        return AlertDialog(
          title: Text(title),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [Text(currentLocation)],
          ),
          actions: !locationSuccess
              ? [
                  TextButton(
                    child: const Text("取消"),
                    onPressed: () {
                      Get.back();
                    },
                  ),
                  TextButton(
                    child: const Text("重新定位"),
                    onPressed: () {
                      _stopLocation();
                      startLocation();
                      ToastUtils.showToast("已开始重新定位");
                      Get.back();
                    },
                  ),
                ]
              : [],
        );
      },
    );
  }

  String getAdCode() {
    if (Platform.isAndroid) {
      return "4ade3d8f31d914903631dd001b1d1d16";
    }
    return "38b47b267c5afb33787aee1fe6b1562d";
  }

  void requestWeather() async {
    Map<String, dynamic> map = {
      "key": "cf52e3c34fe43c0b4e2f94564804434b",
      "city": _adCode,
    };
    String url = HttpHelper.weather;
    dio.Response response = await DioUtils.instance.getCommonRequest(
      url: url,
      queryParameters: map,
    );

    if (response != null) {
      int status = response.statusCode;
      if (status == 0) {
        _currentWeatherInfo = "暂无天气信息";
      } else {
        Map<String, dynamic> resoneseMap = response.data;
        //转换
        dynamic lives = resoneseMap["lives"];
        if (lives != null && lives is List && lives.isNotEmpty) {
          Map<String, dynamic> map = lives[0];
          _currentWeatherInfo = "${map["weather"]}";
          UserHelper.getInstance.currentWeatherInfo = _currentWeatherInfo;
        } else {
          _currentWeatherInfo = "暂无天气信息";
        }
      }
    }

    update(["locationRoot"]);
  }
}
